/**
 * @file{同步 cf 精度检测工站库}
 */
 'use strict';

 const LRU = require("lru-cache");
 const schedule = require('node-schedule');
 const {initFlawData} = require('../../model/pol/flaw');
 const {initFlawFilterData} = require('../../model/pol/flaw_filter');
 const {initJobData} = require('../../model/pol/job');
 const {initPanelData} = require('../../model/pol/panel');

 const options = {
    max: 500,
    length: function (n, key) { return n * 2 + key.length },
    dispose: function (key, n) { n.close() },
    maxAge: 1000 * 60 * 60
 }
 /**
  * 同步pol工站数据基类
  */
 class PolBase {

    constructor (tableModel, sequelize_source, sequelize_aim, stationName, mujian) {
        // 初始化缓存
        this.cache = new LRU(options);
        //各个表的操作模型对象
        this.FlawFilterPol = tableModel.FlawFilterPol;
        this.PanelPol = tableModel.PanelPol;
        this.JobPol = tableModel.JobPol;
        this.FlawPol = tableModel.FlawPol;
        this.mujian = mujian;

        this.sequelize_source = sequelize_source;
        this.sequelize_aim = sequelize_aim;
        this.stationName = stationName;
        // 初始化各个表
        initFlawData(this.sequelize_aim);
        initFlawFilterData(this.sequelize_aim);
        initJobData(this.sequelize_aim);
        initPanelData(this.sequelize_aim);
        // 获取当前执行位置
        this.getSyncPosition();
        // 开始定时缓存任务
        let job = schedule.scheduleJob('*/2 * * * * *', () => {
            this.handPanelInfo(); // panel
            this.handJobInfo(); // job
            this.handFlawInfo(); // Flaw
            this.handFlawFilterInfo(); //flaw_filter
        })
    }
    /**
     * 获取各个表的同步位置
     */
    async getSyncPosition () {
        this.panelUid = await this.getMaxUidfromAimLibrary('panel');
        this.jobUid = await this.getMaxUidfromAimLibrary('job');
        this.flawUid = await this.getMaxUidfromAimLibrary('flaw');
        this.FlawFilterId = await this.getMaxUidfromAimLibrary('flaw_filter');
        // 缺陷分类的id与panelUid保持一致
        this.flawFilterUid = this.panelUid ? this.panelUid : 1;
    }
     /**
     * 获取最新同步的位置
     * @param {String} tableName 表名
     * @return 同步的最新uid
     */
    async getMaxUidfromAimLibrary(tableName) {
        switch (tableName) {
            case 'panel':
                return this.PanelPol.getLatestPanelId(this.sequelize_aim);
                break;
            case 'job':
                return this.JobPol.getLatestJobId(this.sequelize_aim);
                break;
            case 'flaw':
                return this.FlawPol.getLatestFlawId(this.sequelize_aim);
                break;
            case 'flaw_filter':
                return this.FlawFilterPol.getLatestFlawFilterId(this.sequelize_aim, this.panelUid ? this.panelUid : 1);
                break;
            default:
                break;
        }
    }
    /**
     * hand FlawFilter
     * @param {String} panelId
     */
    async handFlawFilterInfo (panelId) {
        if (panelId) {
            let res = await this.FlawFilterPol.getFlawFilterInfoByPanelId(this.sequelize_source, panelId);
            let map  = new Map();
            let flawFilterArray = [];
            for (let i = 0; i < res.length; i++) {
                if (map.has(res[i].flaw_class_type)) {
                    map.set(res[i].flaw_class_type, {
                        ...res[i],
                        flaw_count: ++map.get(res[i].flaw_class_type).flaw_count
                    });
                } else {
                    map.set(res[i].flaw_class_type, {
                        ...res[i],
                        flaw_count: 1
                    });
                }
            }
            for (const i of map) {
                flawFilterArray.push(i[1]);
            }
            return flawFilterArray;
        }
        // flaw表的最新的SheetId
        let sheetId = await this.FlawFilterPol.getMaxSheetIds(this.sequelize_source);
        // 保证所有缺陷都统计上了
        if (this.flawFilterUid < sheetId) {
            let res = await this.FlawFilterPol.getFlawFilterInfoByPanelId(this.sequelize_source, this.flawFilterUid);
            // 缺陷分类计算【算法】 利用map的特点优化遍历
            let map  = new Map();
            let flawFilterArray = [];
            for (let i = 0; i < res.length; i++) {
                if (map.has(res[i].flaw_class_type)) {
                    map.set(res[i].flaw_class_type, {
                        ...res[i],
                        flaw_count: ++map.get(res[i].flaw_class_type).flaw_count
                    });
                } else {
                    map.set(res[i].flaw_class_type, {
                        ...res[i],
                        flaw_count: 1
                    });
                }
            }
            // flawFilter ID开始的位置
            let maxFlawFilterId = this.FlawFilterId !== null ? this.FlawFilterId : await this.FlawFilterPol.getLatestFlawFilterId(this.sequelize_aim);
            // console.log(maxFlawFilterId);
            let index = 1;
            for (const i of map) {
                flawFilterArray.push({
                    ...i[1],
                    id: maxFlawFilterId + index
                })
                index++;
            }
            // console.log(flawFilterArray);
            // 汇总到汇总库
            this.mujian.updateFlawFilterInfo(flawFilterArray);
            console.log(`" **${this.stationName}** " 的flaw数据已经上传完毕，flaw_flilter统计完成，马上post到目标库`);
            //post目标库
            this.postDataToLineDb(this.FlawFilterPol, flawFilterArray, 'flaw_filter');
            this.flawFilterUid++;
            this.FlawFilterId = null;
        } else {
            console.log(`" **${this.stationName}** " 的flaw数据还没上传完，将会继续Loop`);
        }
    }
    /**
     * hand  Flaw
     * @param {String} panelId
     */
    async handFlawInfo (panelId) {
        if (panelId) {
            let res = await this.FlawPol.getFlawInfoByPanelId(this.sequelize_source, panelId);
            return res;
        }
        let res = await this.FlawPol.getFlawInfoByPanelId(this.sequelize_source, this.flawUid ? this.flawUid : 0);
        // console.log(res);
        if (res.length) {
            // 更新当前同步的位置
            this.flawUid = res[res.length - 1].uid;
            // 汇总到汇总库
            this.mujian.updateFLawInfo(res);
            // post 目标库
            this.postDataToLineDb(this.FlawPol, res, 'flaw');
        } else {
            console.log(`" **${this.stationName}** " Flaw表已是最新`);
        }
    }
    /**
     * hand job
     * @param {String} panelId
     */
    async handJobInfo (panelId) {
        if (panelId) {
            let res = await this.JobPol.getJobInfoByPanelId(this.sequelize_source, panelId);
            return res;
        }
        let res = await this.JobPol.getJobInfoByPanelId(this.sequelize_source, this.jobUid ? this.jobUid : 1);
        // console.log(res);
        if (res) {
            // 存进目标库
            this.postDataToLineDb(this.JobPol, res, 'job');
            let maxJobUid = await this.JobPol.getMxUidfromSourceJob(this.sequelize_source);
            // 没到最新位置，一直往最新位置更新
            this.jobUid < maxJobUid ? this.jobUid++ : this.jobUid;
        } else {
            console.log(`" **${this.stationName}** " 没查到job信息!`);
        }
    }
    /**
     * hand panel
     * @param {String} panelId
     */
    async handPanelInfo (panelId) {
        if (panelId) {
            let panelInfo = await this.PanelPol.getLatestPanel(this.sequelize_source, panelId);
            if (!panelInfo) return [];
            let panelPolInfo = {
                ...panelInfo,
                is_ok: panelInfo.flaw_count > 0 ? 0 : 1,
            }
            // 剔除掉三个不要的属性
            delete panelPolInfo.head_md;
            delete panelPolInfo.create_time;
            delete panelPolInfo.sheet_id_seq;
            return panelInfo;
        }
        let panelInfo = await this.PanelPol.getLatestPanel(this.sequelize_source, this.panelUid ? this.panelUid : 1);

        if (panelInfo) {
            let panelPolInfo = {
                ...panelInfo,
                is_ok: panelInfo.flaw_count > 0 ? 0 : 1,
            }
            // 剔除掉三个不要的属性
            delete panelPolInfo.head_md;
            delete panelPolInfo.create_time;
            delete panelPolInfo.sheet_id_seq;
            // 汇总到汇总库
            this.mujian.updatePanelInfo(panelPolInfo);
            // 存进目标库
            this.postDataToLineDb(this.PanelPol, panelPolInfo, 'panel');
            // 查询原表panel的最新位置
            let maxPanelUid = this.PanelPol.getMaxUidfromSourcePanel(this.sequelize_source);
            this.panelUid < maxPanelUid ? this.panelUid++ : '';
        } else {
            console.log(`" **${this.stationName}** " Panel表已是最新`);
        }
    }
    /**
     * 上传data到产线db的指定表中
     * @param {} operatorName 表的操作对象
     * @param {Object} data 上传的数据
     * @param {String} tableName 表名
     */
    async postDataToLineDb (operatorName, data, tableName) {
        // 存进目标库
        try {
            let res = await operatorName.uploadPolInfo(data);
            if(res.dataValues || res.length) {
                console.log(`${tableName}上传**${this.stationName}**库sucess!`);
            }else {
                console.log(`${tableName}上传**${this.stationName}**库的数据为空`);
            }
        } catch (error) {
            console.log(`${tableName}上传**${this.stationName}**库failed`);
        }
    }
    /**
     * 获取
     */
    async getNewsDataFromLineDb () {

    }
 }

 module.exports = PolBase;